@node Reader & writer
@section Reader & writer

Scheme48 has simple S-expression reader & writer libraries, with some
facilities beyond R5RS's @code{read} & @code{write} procedures.

@menu

* Reader::
* Writer::

@end menu

@node Reader
@subsection Reader

@stindex reading
Scheme48's reader facility is exported by the @code{reading}
structure.  The @code{read} binding thereby exported is identical to
that of the @code{scheme} structure, which is the binding that R5RS
specifies under the name @code{read}.

@deffn procedure read [port] @returns{} readable-value
Reads a single S-expression from @var{port}, whose default value is the
current input port.  If the end of the stream is encountered before the
beginning of an S-expression, @code{read} will return an EOF object.
It will signal a read error if text read from @var{port} does not
constitute a complete, well-formed S-expression.
@end deffn

@deffn procedure define-sharp-macro char proc @returns{} unspecified
Defines a sharp/pound/hash/octothorpe (@code{#}) reader macro.  The
next time the reader is invoked, if it encounters an octothorpe/sharp
followed by @var{char}, it applies @var{proc} to @var{char} and the
input port being read from.  @var{Char} is @emph{not} consumed in the
input port.  If @var{char} is alphabetic, it should be lowercase;
otherwise the reader will not recognize it, since the reader converts
the character following octothorpes to lowercase.
@end deffn

@deffn procedure reading-error port message irritant @dots{} @returns{} unspecified
Signals an error while reading, for custom sharp macros.  It is not
likely that calls to @code{reading-error} will return.
@end deffn

@deffn procedure gobble-line port @returns{} unspecified
Reads until a newline from @var{port}.  The newline character sequence
is consumed.
@end deffn

@node Writer
@subsection Writer

@stindex writing
Scheme48's @code{writing} structure exports its writer facility.  The
@code{write} and @code{display} bindings from it are identical to those
from the @code{scheme} structure, which are the same bindings that R5RS
specifies.

@deffn procedure write object [port] @returns{} unspecified
Writes @var{object} to @var{port}, which defaults to the current output
port, in a machine-readable manner.  Strings are written with
double- quotes; characters are prefixed by @code{#\}.  Any object that
is unreadable --- anything that does not have a written representation
as an S-expression --- is written based on its @dfn{disclosed}
representation. Such unreadable objects are converted to a disclosed
representation by the @code{disclose} generic procedure (see below).
@end deffn

@deffn procedure display object [port] @returns{} unspecified
Displays @var{object} to @var{port}, which defaults to the value of the
current output port, in a more human-readable manner.  Strings are
written without surrounding double-quotes; characters are written as
themselves with no prefix.
@end deffn

@cindex customized writer
@cindex writer, customized
@deffn procedure recurring-write object port recur @returns{} unspecified
Writes @var{object} to @var{port}.  Every time this recurs upon a new
object, rather than calling itself or its own looping procedure, it
calls @var{recur}.  This allows customized printing routines that still
take advantage of the existence of Scheme48's writer.  For example,
@code{display} simply calls @code{recurring-write} with a recurring
procedure that prints strings and characters specially and lets
@code{recurring-write} handle everything else.
@end deffn

@deffn procedure display-type-name name port @returns{} unspecified
If @var{name} is a symbol with an alphabetic initial character, this
writes @var{name} to @var{port} with the first character uppercased and
the remaining character lowercased; otherwise, @code{display-type-name}
simply writes @var{name} to @var{port} with @code{display}.

@lisp
(display-type-name 'foo)
    @print{} Foo

(display-type-name (string->symbol "42foo"))
    @print{} 42foo

(display-type-name (cons "foo" "bar"))
    @print{} (foo . bar)

(display-type-name (string->symbol "fOo-BaR"))
    @print{} Foo-bar@end lisp

@noindent
This is used when printing disclosed representations (see below).
@end deffn

@subsubsection Object disclosure

@cindex customized writer
@cindex writer, customized
@stindex methods
The @embedref{Generic dispatch system, @code{methods} structure}
exports the generic procedure @code{disclose} and its method table
@code{&disclose}. When @code{recurring-write} encounters an object it
is unable to write in a rereadable manner, it applies @code{disclose}
to the unreadable object to acquire a @dfn{disclosed representation.}
(If @code{disclose} returns @code{#f}, @ie{} the object has no
disclosed representation, the writer will write @code{#@{Random
object@}}.) After converting a value to its disclosed representation,
@eg{} a list consisting of the symbol @code{foo}, the symbol
@code{bar}, a byte vector, and a pair @code{(1 . 2)}, the writer will
write @code{#@{Foo #@{Byte-vector@} bar (1 . 2)@}}.  That is: contents
of the list are surrounded by @code{#@{} and @code{@}}, the first
element of the list (the `type name') is written with
@code{display-type-name}, and then the remaining elements of the list
are recursively printed out with the @var{recur} argument.

Typically, when a programmer creates an abstract data type by using
Scheme48's record facility, he will not add methods to @code{&disclose}
but instead define the record type's discloser with the
@code{define-record-discloser} procedure; @pxref{Records}.

Example:

@lisp
(define-record-type pare rtd/pare
  (kons a d)
  pare?
  (a kar set-kar!)
  (d kdr set-kdr!))

(define-record-discloser rtd/pare
  (lambda (pare)
    `(pare ,(kar pare) *dot* ,(kdr pare))))

(write (kons (kons 5 3) (kons 'a 'b)))
    @print{} #@{Pare #@{Pare 5 *dot* 3@} *dot* #@{Pare a *dot* b@}@}@end lisp
